home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fritz: All Fritz
/
All Fritz.zip
/
All Fritz
/
FILES
/
PROGBLER
/
ASMCODE3.LZH
/
CLOCK.ASM
< prev
next >
Wrap
Assembly Source File
|
1985-05-11
|
11KB
|
338 lines
PAGE 66,132
;****************************************************************************
;
; PROGRAM: CLOCK
;
; DESCRIPTION: PRINT DATE AND TIME ON SCREEN
;
; INPUT: NONE
;
; OUTPUT: CURRENT DATE AND TIME ON SCREEN
;
; TYPE OF FILE: .COM FILE
;
; COMMENTS: THIS PROGRAM WILL PICK UP THE CURRENT DATE AND TIME AND
; DISPLAY DAY, DATE AND TIME ON THE SCREEN. DATE IS FORMATTED OUT
; TO MONTH NAME, DAY AND YEAR, TIME IS HH:MM:SS. THIS PROGRAM WILL
; LOOP UNTIL CONTROL BREAK IS INTERCEPTED.
;
; TO INCREASE READABILITY OF THE DISPLAY, IT WILL SAVE THE CURRENT
; CURSOR TYPE, AND ERASE THE CURSOR. WHEN CONTROL-BREAK IS DETECTED,
; THE PROGRAM WILL INTERCEPT THE INTERRUPT AT ROUTINE TERMIN, RESTORE
; THE CURSOR AND TERMINATE.
;
; THIS PROGRAM ALSO CHECKS FOR DOS 2.0 OR ABOVE, AND IF IT IS NOT
; PRESENT, TERMINATE IMMEDIATELY
;
; THIS PROGRAM USES THE EQUATIONS FROM WES MEIER'S DFACT.BAS TO COMPUTE
; THE DAY OF THE WEEK. THEY ARE:
;
; F = 365 * YEAR + DAY + (31 * (MONTH - 1))
;
; IF MONTH < 3 THEN F = F + INT ((YEAR - 1) / 4) -
; INT ((INT ((YEAR / 100) + 1)) * 3 / 4)
;
; IF MONTH >= 3 THEN F = F + INT ((MONTH + 23) * 4 / 10) +
; INT (YEAR / 4) - INT ((INT (YEAR / 100) + 1) * 3 / 4)
;
; DAY NUMBER = F MOD 7 (REMAINDER OF F / 7) AND IS FIGURED AS
;
; WHERE 0 = SATURDAY, 1 = SUNDAY, ETC.
;
; NOTE: THE DAY NUMBER IS FIGURED AS (F MOD 7000) MOD 7 TO
; PREVENT AN OVERFLOW CAUSED BY DIVIDING A LARGE NUMBER
; BY A SMALL ONE.
;
; THIS PROGRAM IS MADE TO RUN AS A .COM FILE, AND MUST BE RUN THROUGH
; EXE2BIN.EXE IN ORDER TO OPERATE CORRECTLY
;
;****************************************************************************;
IF1 ;DURING PASS 1
INCLUDE ASSEMBLE.MAC ;INCLUDE MACRO LIBRARY
ENDIF
;
COLUMNS EQU 80 ;NUMBER OF COLUMNS ON SCREEN
;
BDATES STRUC ;STRUCTURE FOR BINARY DATE
MONTH DB 0 ;BYTE MONTH
DAY DB 0 ;BYTE DAY
YEAR DW 0 ;WORD YEAR
BDATES ENDS
;
DATETIME SEGMENT PARA PUBLIC 'CODE'
ASSUME CS:DATETIME, DS:DATETIME, ES:DATETIME, SS:NOTHING
ORG 100H ;SET ORIGIN TO XXXX:0100H
ENTRY LABEL NEAR ;ENTRY POINT
JMP CODE_START ;JUMP AROUND DATA AREAS
DB 'CLOCK.ASM' ;COPYRIGHT NOTICE
DB 'COPYRIGHT (C) 1983'
DB 'JERRY D. STUCKLE'
DB 'PUBLIC DOMAIN SOFTWARE' ;PROGRAM FOR PUBLIC DOMAIN
CSRSAVE DW ? ;CURSOR MODE SAVE AREA
WRKAREA DB 11 DUP (?) ;WORK AREA
TIME DB 8 DUP (0),'$' ;AREA FOR ASCII TIME
BDATE BDATES <,,> ;BINARY DATE AREA
CURRDAY DB 10 DUP (?) ;AREA FOR ASCII DAY
DATEOUT DB 20 DUP (?) ;AREA FOR ASCII DATE
DOSERR DB 'DOS 2.0 OR ABOVE REQUIRED. PROGRAM TERMINATED.',0AH,0DH
;
MO_TBL LABEL WORD ;POINTER TO MONTH NAMES
DW OFFSET JAN ;JANUARY
DW OFFSET FEB ;FEBRUARY
DW OFFSET MAR ;MARCH
DW OFFSET APR ;APRIL
DW OFFSET MAY ;MAY
DW OFFSET JUN ;JUNE
DW OFFSET JUL ;JULY
DW OFFSET AUG ;AUGUST
DW OFFSET SEP ;SEPTEMBER
DW OFFSET OCT ;OCTOBER
DW OFFSET NOV ;NOVEMBER
DW OFFSET DEC ;DECEMBER
; ;ASCIIZ STRINGS FO MONTH NAMES
JAN DB 'JANUARY ',0
FEB DB 'FEBRUARY ',0
MAR DB 'MARCH ',0
APR DB 'APRIL ',0
MAY DB 'MAY ',0
JUN DB 'JUNE ',0
JUL DB 'JULY ',0
AUG DB 'AUGUST ',0
SEP DB 'SEPTEMBER ',0
OCT DB 'OCTOBER ',0
NOV DB 'NOVEMBER ',0
DEC DB 'DECEMBER ',0
;
;
DAY_NAM LABEL WORD ;POINTER TO DAY NAMES
DW OFFSET SAT ;SATURDAY
DW OFFSET SUN ;SUNDAY
DW OFFSET MON ;MONDAY
DW OFFSET TUE ;TUESDAY
DW OFFSET WED ;WEDNESDAY
DW OFFSET THU ;THURSDAY
DW OFFSET FRI ;FRIDAY
; ;ASCIIZ STRINGS OF DAY NAMES
SAT DB 'SATURDAY',0
SUN DB 'SUNDAY',0
MON DB 'MONDAY',0
TUE DB 'TUESDAY',0
WED DB 'WEDNESDAY',0
THU DB 'THURSDAY',0
FRI DB 'FRIDAY',0
;
CODE_START LABEL NEAR
;
; FIRST, WE CLEAR THE SCREEN. THEN, IF NOT AT AT LEAST DOS 2.0,
; WE TERMINATE THE PROGRAM.
;
CLS
DOSCALL 30H ;GET DOS VERSION NUMBER
CMP AL,2 ;AT LEAST DOS 2.0?
JGE CONT ;YES - CONTINUE
DISPLAY DOSERR ;NO - DISPLAY DOS ERROR MESSAGE
INT 20H ;AND TERMINATE
;
; SAVE THE CURSOR MODE, THEN ERASE IT
; ALSO, SET THE CONTROL-BREAK INTERRUPT VECTOR
;
CONT: ;DOS VERSION GOOD
CURSOR SAVE,CSRSAVE ;SAVE CURSOR MODE
CURSOR ERASE ;ERASE CURSOR
SETINT 23H,TERMIN ;SET CNTL-BREAK VECTOR
CALL PROCESS_DATE ;GET THE DATE
;
; DATE PROCESSING IS COMPLETE. PROCESS THE TIME
; NOTE: WHEN DX IS LOADED, THE 2 CHARACTERS ARE SWAPPED, SO THE
; COMPARE '32' IS FOR THE 23'RD HOUR.
;
PROCESS_TIME:
GETTIME WRKAREA,CHAR ;GET CURRENT TIME IN ASCII
MOV DX,WORD PTR TIME ;GET OLD HOUR IN DH
MOVE TIME,WRKAREA,8 ;MOVE IT INTO THE TIME FIELD
CMP DX,WORD PTR TIME ;SAME AS NEW AREA?
JE SHOW_TIME ;YES - NO NEED TO DISPLAY DATE
CMP DX,'32' ;WAS IT 23:XX:XX?
JNE SHOW_TIME ;NO - DON'T DISPLAY THE DATE
CALL PROCESS_DATE ;DAY HAS CHANGED - DISPLAY IT
SHOW_TIME:
LOCATE 15,(COLUMNS-8)/2 ;LOCATE THE CURSOR
DISPLAY TIME ;AND DISPLAY IT
JMP PROCESS_TIME ;AND GO PROCESS THE TIME AGAIN
;
; GET THE CURRENT DATE AND PROCESS IT
;
PROCESS_DATE PROC NEAR ;PROCESS DATE
GETDATE BDATE,BIN ;GET CURRENT DATE IN BINARY
;
; F = 365 * YEAR + DAY + (31 * (MONTH - 1))
;
MOV AX,BDATE.YEAR ;GET CURRENT YEAR
SAVE AX ;SAVE ON STACK
MOV BX,365 ;NUMBER OF DAYS IN A YEAR
MUL BX ;MULTIPLY
CLEAR BH ;CLEAR BH
MOV BL,BDATE.DAY ;GET THE DAY
ADD AX,BX ;ADD TO AX
ADC DX,0 ;ADD ANY CARRY TO DX
MOV WORD PTR WRKAREA,AX ;SAVE IN WORK AREA
MOV WORD PTR WRKAREA+2,DX ;SAVE HIGH ORDER, TOO.
CLEAR AH ;CLEAR AH
MOV AL,BDATE.MONTH ;GET THE MONTH
DEC AL ;DECREMENT
MOV BL,31 ;MAX DAYS IN MONTH
MUL BL ;MULTIPLY
ADD WORD PTR WRKAREA,AX ;ADD TO WRKAREA
ADC WORD PTR WRKAREA+2,0 ;ADD ANY CARRY
;NOW WE MUST USE ONE OF TWO DIFFERENT ROUTINES
CMP BDATE.MONTH,3 ;JANUARY OR FEBRUARY?
JGE PROCESS_DATE_2 ;NO - GO TO SECOND ROUTINE
;
; IF MONTH < 3 THEN F = F + INT ((YEAR - 1) / 4) -
; INT ((INT ((YEAR / 100) + 1)) * 3 / 4)
;
RESTORE AX ;GET YEAR BACK
DEC AX ;DECREMENT UEAR
SAVE AX ;AND SAVE IT AGAIN
SHR AX,1 ;DIVIDE BY 2...
SHR AX,1 ;AND AGAIN.
ADD WORD PTR WRKAREA,AX ;ADD TO WORK AREA
ADC WORD PTR WRKAREA+2,0 ;ADD ANY CARRY
RESTORE AX ;GET (YEAR-1) BACK
MOV BL,100 ;100 TO DL
DIV BL ;AND DIVIDE
INC AL ;INCREMENT IT
MOV BL,3 ;MULTIPLY BY 3...
MUL BL ;DO IT
SHR AX,1 ;DIVIDE BY 2...
SHR AX,1 ;AND THEN AGAIN.
CLEAR AH ;THROW AWAY REMAINDER
SUB WORD PTR WRKAREA,AX ;SUBTRACT NUMBER OF LEAP DAYS
SBB WORD PTR WRKAREA,0 ;AND ANY BORROW REQUIRED.
JMP PROCESS_DATE_3 ;GO BACK TO COMMON ROUTINE
PROCESS_DATE_2:
;
; IF MONTH >= 3 THEN F = F + INT ((MONTH + 23) * 4 / 10) +
; INT (YEAR / 4) - INT ((INT (YEAR / 100) + 1) * 3 / 4)
;
MOV AL,BDATE.MONTH ;GET THE MONTH IN AL
CLEAR AH ;CLEAR HIGH ORDER BYTE
SHL AX,1 ;MULTIPLY BY 2...
SHL AX,1 ;AND AGAIN BY 2
ADD AX,23 ;ADD 23
MOV BL,10 ;MOVE 10 TO BL
DIV BL ;AND DIVIDE
CLEAR AH ;THROW OUT REMAINDER
SUB WORD PTR WRKAREA,AX ;SUBTRACT FROM WORK AREA
SBB WORD PTR WRKAREA+2,0 ;AND SUBTRACT ANY BORROW.
RESTORE AX ;GET YEAR BACK
SAVE AX ;SAVE IT AGAIN
SHR AX,1 ;DIVIDE BY 2
SHR AX,1 ;AND DO IT AGAIN
ADD WORD PTR WRKAREA,AX ;ADD TO WORK AREA
ADC WORD PTR WRKAREA+2,0 ;ADD ANY CARRY
RESTORE AX ;GET (YEAR-1) BACK
MOV BL,100 ;100 TO DL
DIV BL ;AND DIVIDE
INC AL ;INCREMENT IT
MOV BL,3 ;MULTIPLY BY 3...
MUL BL ;DO IT
SHR AX,1 ;DIVIDE BY 2...
SHR AX,1 ;AND THEN AGAIN.
CLEAR AH ;THROW AWAY REMAINDER
SUB WORD PTR WRKAREA,AX ;SUBTRACT NUMBER OF LEAP DAYS
SBB WORD PTR WRKAREA,0 ;AND ANY BORROW REQUIRED.
PROCESS_DATE_3:
;
; DAY NUMBER = (F MOD 7000) MOD 7
;
MOV AX,WORD PTR WRKAREA ;GET TOTAL IN AX...
MOV DX,WORD PTR WRKAREA+2 ;AND HIGH ORDER IN DX
MOV BX,7000 ;DIVIDE BY 7000 SO WE...
DIV BX ;...DON'T GET AN OVERFLOW
MOV AX,DX ;REMAINDER TO AX
CLEAR DX ;CLEAR HIGH ORDER WORD
MOV BX,7 ;NOW DIVIDE BY 7 IN 32...
DIV BX ;BIT MODE SO WE DON'T OVERFLOW.
MOV BX,DX ;GET DAY NUMBER IN BL
SHL BX,1 ;SHIFT FOR TABLE LOOKUP
MOV SI,WORD PTR DAY_NAM [BX] ;GET DAY NAME
LEA DI,CURRDAY ;GET ADDRESS OF DAY AREA
CLD ;SET INCREMENT
;
; WE HAVE THE CURRENT DAY. MOVE IT INTO THE WORK AREA AND DISPLAY
; IT, CENTERED. FORMULA FOR CENTERING IS (COLUMNS+1-LENGTH)/2
; AND IS FIGURED BY ((START ADDRESS+COLUMNS+1)-END ADDRESS)/2
;
DAY_LOOP:
MOVSB ;MOVE A BYTE
CMP BYTE PTR [SI],0 ;END OF STRING?
JNE DAY_LOOP ;NO - WE'RE NOT DONE
MOV BYTE PTR [DI],'$' ;MOVE IN A '$'
LEA BX,CURRDAY+(COLUMNS+1) ;START ADDRESS + LINE LENGTH
SUB BX,DI ;SUBTRACE END ADDRESS
SHR BL,1 ;AND DIVIDE BY 2
CLS ;CLEAR THE SCEEN
LOCATE 11,BL ;LOCAT THE CURSOR
DISPLAY CURRDAY ;AND DISPLAY THE DAY
;
; NOW WE MUST MOVE THE CURRENT MONTH INTO THE STRING
;
MOV BL,BDATE.MONTH ;GET CURRENT MONTH
DEC BL ;DECREMENT FOR TABLE LOOKUP
SHL BX,1 ;MULTIPLY BY 2
MOV SI,MO_TBL[BX] ;GET ADDRESS OF MONTH NAME
LEA DI,DATEOUT ;GET TO STRING ADDRESS
CLD ;INCREMENT ADDRESSES
MONTH_LOOP: ;MOVE THE MONTH NAME
MOVSB ;NO - MOVE THE BYTE
CMP BYTE PTR [SI],0 ;IS THE NEXT BYTE 0?
JNE MONTH_LOOP ;AND GO CHECK THE NEXT BYTE
;
; CURRENT MONTH NAME IS READY. LET'S GET THE DAY NEXT, CONVERT IT
; TO ASCII, AND PUT IT IN THE STRING
;
MOVE_DAY:
MOV AL,BDATE.DAY ;GET THE DAY IN AL
AAM ;CONVERT TO UNPACKED DECIMAL
OR AX,3030H ;CONVERT TO ASCII
CMP AH,'0' ;IS THE FIRST CHARACTER 0?
JE MOVE_LOW_DATE ;YES - DO NOT MOVE IT
MOV BYTE PTR [DI],AH ;NO - MOVE IT
INC DI ;AND INCREMENT DESTINATION
MOVE_LOW_DATE:
MOV BYTE PTR [DI],AL ;MOVE IN LOW DATE
INC DI ;POINT TO NEXT BYTE
MOV BYTE PTR [DI],',' ;MOVE IN A COMMA
INC DI ;POINT TO NEXT BYTE
MOV BYTE PTR [DI],' ' ;A SPACE GOES HERE
INC DI ;AND POINT AT NEXT BYTE
;
; DAY PROCESSING IS COMPLETE, NOW DO THE SAME TO THE YEAR
;
MOV AX,BDATE.YEAR ;GET CURRENT YEAR
SAVE DI ;SAVE DESTINATION ADDRESS
CVD WRKAREA,BDATE.YEAR ;CONVERT THE YEAR TO ASCII
RESTORE DI ;RESTORE DESTINATION ADDRESS
MOVE [DI],WRKAREA,4 ;MOVE YEAR TO DESTINATION
MOV BYTE PTR [DI],'$' ;SET A '$' AT THE END
;
; STRING IS BUILT. CENTER IT USING THE SAME EQUATION AS THE DAY.
;
LEA BX,DATEOUT+COLUMNS ;START ADDRESS + LINE LENGTH
SUB BX,DI ;SUBTRACE END ADDRESS
SHR BX,1 ;AND DIVIDE BY 2
LOCATE 13,BL ;LOCATE THE CURSOR
DISPLAY DATEOUT ;AND DISPLAY THE DATE
RET ;RETURN TO CALLER
PROCESS_DATE ENDP
TERMIN PROC NEAR ;TERMINATION PROCEDURE
CURSOR SET,CSRSAVE ;RESTORE CURSOR
CLS ;CLEAR THE SCREEN
CLEAR AX ;RETURN CODE 0
DOSCALL 4CH ;AND TERMINATE
TERMIN ENDP
DATETIME ENDS
END ENTRY